﻿
INLINE VOID AlphaBlend32LevelSSE2(LPCWORD, LPWORD, LPCBYTE);

//////////////////////////////////////////////////////////////////////////

INLINE VOID AlphaBlend32LevelSSE2(LPCWORD src, LPWORD dest, LPCBYTE alpha)
{
	// mm4 = THREETHREE (00030003000300030003000300030003h)
	// mm5 = COLORMASK (07E0F81F07E0F81F07E0F81F07E0F81Fh)

	// 公式 dest = (src - dest) * alpha / 32 + dest
	// 一次同时计算2个像素
	__asm
	{
		// 一次性装载4个APLHA到mm7
		mov			esi, alpha
		mov			ecx, [esi]
		jecxz		quit
		mov			esi, src
		mov			edi, dest
		movd		xmm7, ecx				// ........ ....AaAa

		// 分组扩展ALPHA
		punpcklbw	xmm7, xmm7				// ........ AAaaAAaa
		pxor		xmm0, xmm0				// ........ ........
		punpcklbw	xmm7, xmm0				// .A.A.a.a .A.A.a.a
		paddw		xmm7, xmm4				// ALPHA误差补正
		psrlw		xmm7, 3					// 只保留32级ALPHA

		// 分别一次性装载源和目标的4个像素到xmm0和xmm1
		movq		xmm0, qword ptr [esi]	// [......][......][RGBrgb][RGBrgb]
		movq		xmm1, qword ptr [edi]	// [......][......][RGBrgb][RGBrgb]

		// 分组扩展像素
		punpcklwd	xmm0, xmm0				// [RGBRGB][rgbrgb][RGBRGB][rgbrgb]
		pand		xmm0, xmm5				// [.G.R.B][.g.r.b][.G.R.B][.g.r.b]
		punpcklwd	xmm1, xmm1				// [RGBRGB][rgbrgb][RGBRGB][rgbrgb]
		pand		xmm1, xmm5				// [.G.R.B][.g.r.b][.G.R.B][.g.r.b]

		// 混色计算
		psubd		xmm0, xmm1				// xmm0 = src - dest
		movdqa		xmm2, xmm0
		pmullw		xmm0, xmm7				// [Gx.xBx][gx.xbx][Gx.xBx][gx.xbx]
		pmulhuw		xmm2, xmm7				// [.....R][.....r][.....R][.....r]
		pslldq		xmm2, 2					// [..R...][..r...][..R...][..r...]
		paddd		xmm0, xmm2				// [GxRxBx][gxrxbx][GxRxBx][gxrxbx]
		psrld		xmm0, 5					// [.GxRxB][.gxrxb][.GxRxB][.gxrxb]
		paddd		xmm0, xmm1				// + dest
		pand		xmm0, xmm5				// [.G.R.B][.g.r.b][.G.R.B][.g.r.b]

		// 恢复像素
		pshuflw		xmm1, xmm0, 0b1h		// [.G.R.B][.g.r.b][R.B.G.][r.b.g.]
		pshufhw		xmm1, xmm1, 0b1h		// [R.B.G.][r.b.g.][R.B.G.][r.b.g.]
		por			xmm1, xmm0				// [RGBRGB][rgbrgb][RGBRGB][rgbrgb]=[C3C3][C2C2][C1C1][C0C0]
		pshuflw		xmm0, xmm1, 0d8h		// [C3C3][C2C2][C1C0][C1C0]
		pshufhw		xmm0, xmm0, 0d8h		// [C3C2][C3C2][C1C0][C1C0]
		pshufd		xmm1, xmm0, 0d8h		// [C3C2][C1C0][C3C2][C1C0]

		// 保存结果
		movq		qword ptr [edi], xmm1

quit:
	}
}

//////////////////////////////////////////////////////////////////////////
